设备树解析的大致流程

您所在的位置:网站首页 uboot 查看设备树 设备树解析的大致流程

设备树解析的大致流程

2024-01-31 17:23| 来源: 网络整理| 查看: 265

u-boot启动的最后阶段获得linux对应os启动函数后执行它

do_bootm_linux int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images) { /* No need for those on ARM */ if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE) return -1; if (flag & BOOTM_STATE_OS_PREP) { boot_prep_linux(images);//在里面会将bootargs的参数放在dts文件的chosen节点下,所以后面r2传递的是dtb而不是args return 0; } if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) { boot_jump_linux(images, flag); return 0; } boot_prep_linux(images); boot_jump_linux(images, flag);//goto return 0; } boot_jump_linux static void boot_jump_linux(bootm_headers_t *images, int flag) { #ifdef CONFIG_ARM64 void (*kernel_entry)(void *fdt_addr, void *res0, void *res1, void *res2); int fake = (flag & BOOTM_STATE_OS_FAKE_GO); kernel_entry = (void (*)(void *fdt_addr, void *res0, void *res1, void *res2))images->ep; debug("## Transferring control to Linux (at address %lx)...\n", (ulong) kernel_entry); bootstage_mark(BOOTSTAGE_ID_RUN_OS); announce_and_cleanup(fake);//会打印Starting Kernel..... if (!fake) { do_nonsec_virt_switch(); kernel_entry(images->ft_addr, NULL, NULL, NULL); } #else unsigned long machid = gd->bd->bi_arch_number; char *s; void (*kernel_entry)(int zero, int arch, uint params); unsigned long r2; int fake = (flag & BOOTM_STATE_OS_FAKE_GO); kernel_entry = (void (*)(int, int, uint))images->ep; s = getenv("machid"); if (s) { if (strict_strtoul(s, 16, &machid) #ifdef CONFIG_ARMV7_NONSEC if (armv7_boot_nonsec()) { armv7_init_nonsec(); secure_ram_addr(_do_nonsec_entry)(kernel_entry, 0, machid, r2); } else #endif kernel_entry(0, machid, r2);/*跳到内核的第一行代码,kernel_entry就是内核的第一行代码标号,由于第一行代码是汇编,所以传的是r0,r1,r2 其中: r1 :machid是机器的id,!如果使用设备树的话这个 machid 就无效了, r2: 如果使用设备树的话是设备树地址否则bootargs (通过验证从网络启动时r2是dtb) */ } #endif } setup_arch(由start_kernel调用) void __init setup_arch(char **cmdline_p) { ...... ...... unflatten_device_tree(); ...... }

unflatten_device_tree

void __init unflatten_device_tree(void) { __unflatten_device_tree(initial_boot_params, &of_root, early_init_dt_alloc_memory_arch);//解析平台设备树节点 /* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */ of_alias_scan(early_init_dt_alloc_memory_arch);//解析chosen节点下的bootargs }

__unflatten_device_tree

static void __unflatten_device_tree(void *blob, struct device_node **mynodes, void * (*dt_alloc)(u64 size, u64 align)) { unsigned long size; int start; void *mem; pr_debug(" -> unflatten_device_tree()\n"); if (!blob) { pr_debug("No device tree pointer\n"); return; } pr_debug("Unflattening device tree:\n"); pr_debug("magic: %08x\n", fdt_magic(blob)); pr_debug("size: %08x\n", fdt_totalsize(blob)); pr_debug("version: %08x\n", fdt_version(blob)); if (fdt_check_header(blob)) { pr_err("Invalid device tree blob header\n"); return; } /* First pass, scan for size */ start = 0; size = (unsigned long)unflatten_dt_node(blob, NULL, &start, NULL, NULL, 0, true); size = ALIGN(size, 4); pr_debug(" size is %lx, allocating...\n", size); /* Allocate memory for the expanded device tree */ mem = dt_alloc(size + 4, __alignof__(struct device_node));//分配device_node内存 memset(mem, 0, size); *(__be32 *)(mem + size) = cpu_to_be32(0xdeadbeef); pr_debug(" unflattening %p...\n", mem); /* Second pass, do actual unflattening */ start = 0; unflatten_dt_node(blob, mem, &start, NULL, mynodes, 0, false); if (be32_to_cpup(mem + size) != 0xdeadbeef) pr_warning("End of tree marker overwritten: %08x\n", be32_to_cpup(mem + size)); pr_debug("


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3